amd iommu: Enable guest level translation
authorWei Wang <wei.wang2@amd.com>
Thu, 12 Jan 2012 12:53:20 +0000 (13:53 +0100)
committerWei Wang <wei.wang2@amd.com>
Thu, 12 Jan 2012 12:53:20 +0000 (13:53 +0100)
Similar to nested paging for SVM, IOMMUv2 supports two level
translations for DMA. This patch enables this feature.

Signed-off-by: Wei Wang <wei.wang2@amd.com>
Committed-by: Jan Beulich <jbeulich@suse.com>
xen/drivers/passthrough/amd/iommu_init.c

index 647d3828c70232c59a94a218cf4e98642d59945c..6185ca61bf44ad2c0b68da578a132ed7af937402 100644 (file)
@@ -217,12 +217,29 @@ static void set_iommu_translation_control(struct amd_iommu *iommu,
     entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
 
     enable ?
-        iommu_set_bit(&entry, IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT):
+        iommu_set_bit(&entry, IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT) :
         iommu_clear_bit(&entry, IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT);
 
     writel(entry, iommu->mmio_base+IOMMU_CONTROL_MMIO_OFFSET);
 }
 
+static void set_iommu_guest_translation_control(struct amd_iommu *iommu,
+                                                int enable)
+{
+    u32 entry;
+
+    entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
+
+    enable ?
+        iommu_set_bit(&entry, IOMMU_CONTROL_GT_ENABLE_SHIFT) :
+        iommu_clear_bit(&entry, IOMMU_CONTROL_GT_ENABLE_SHIFT);
+
+    writel(entry, iommu->mmio_base+IOMMU_CONTROL_MMIO_OFFSET);
+
+    if ( enable )
+        AMD_IOMMU_DEBUG("Guest Translation Enabled.\n");
+}
+
 static void set_iommu_command_buffer_control(struct amd_iommu *iommu,
                                                     int enable)
 {
@@ -658,6 +675,9 @@ static void enable_iommu(struct amd_iommu *iommu)
     if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
         set_iommu_ppr_log_control(iommu, IOMMU_CONTROL_ENABLED);
 
+    if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_GTSUP_SHIFT) )
+        set_iommu_guest_translation_control(iommu, IOMMU_CONTROL_ENABLED);
+
     set_iommu_translation_control(iommu, IOMMU_CONTROL_ENABLED);
 
     if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_IASUP_SHIFT) )
@@ -998,6 +1018,9 @@ static void disable_iommu(struct amd_iommu *iommu)
     if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_PPRSUP_SHIFT) )
         set_iommu_ppr_log_control(iommu, IOMMU_CONTROL_DISABLED);
 
+    if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_GTSUP_SHIFT) )
+        set_iommu_guest_translation_control(iommu, IOMMU_CONTROL_DISABLED);
+
     set_iommu_translation_control(iommu, IOMMU_CONTROL_DISABLED);
 
     iommu->enabled = 0;